iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0
Modern Web

前端蛇行撞牆記系列 第 27

Day27 前端蛇行撞牆記 - 表單輸入 input 原生及 v-model 比較 / Vue 3 (上)

  • 分享至 

  • xImage
  •  

前言

自從學了Vue 的 v-model 才發現對原生的 input 行為其實不太了解,而且在 Vue 中的 v-model 幾乎都是用原生的狀態去做出來的,趁這個機會來比較兩者之間相同及不相同的地方。

比較原生跟Vue如何取到 input 值

原生JS

在這個範例中,會把取到 input 的值,再放到 <p>tag 顯示出來。

在原生中,要取到 input 裡面的值必須要先操作DOM拿到這個 input ,拿到 input.value 之後再賦值給 p.textContent

html:

<div class="name-content">
    <label for="name" >name: </label>
    <input type="text" name="name" value="" id="name">
    <p></p>
</div>

javascript:

const input = document.querySelector("input[name=name]")
const text = document.querySelector(".name-content p")

input.addEventListener('input', function(e) {
	text.textContent = input.value;
})

Vue 3 - v-model

Vue 有一個專門處理各種輸入的 v-model,不只可以用在 <input> 也可以用在 <select><textarea> 上。

首先先創一個響應式變數 inputValue 放一個空字串,然後再把這個變數綁在 input 的 v-model 身上,再把下面的 <p>tag 裡面用插值的方式放置變數,就可以取到 input 上的值了。

javascript:

const inputValue = ref('')

template:

<div class="name-content">
    <label for="name" >name: </label>
    <input type="text" v-model="inputValue" name="name" id="name">
    <p>{{ inputValue }}</p>
</div>

就是這麼輕鬆寫意,不過再把 v-model 拆解出來,其實是同時使用了 v-bind: value 以及 v-on: input

一樣先有響應式變數 inputValue ,但是在監聽 input 事件的時候再用 $event.target.value 賦值給 inputValue,這一段其實就很像剛剛原生做的事情,只是 v-model 把這些都包起來了。

template:

<div class="name-content">
    <label for="name" >name: </label>
    <input type="text" v-bind:value="inputValue" @input="inputValue = $event.target.value" name="name" id="name">
    <p>{{ inputValue }}</p>
</div>

小結

但是跟剛剛的比對就知道,原生的 input 是使用監聽 input 事件才能取到當下的值,v-model 的 source code 也是用監聽 input 的事件;然而不是所有 input 都是監聽 input 事件的,可能只有 <input type='text'><textarea> 是如此, input 的 type 這麼多,每個都有不同的使用方法,接下來就會介紹一些特別的 input type。

input[type=checkbox]

會嘗試用一個群組的 checkbox 來做同樣的綁定。

原生

使用 change 去監聽。
<input type="checkbox"> 是一個可以打勾的框框通常會搭配 <label> 當作敘述。

而 checkbox 就不是使用 value 來取到值,他沒有值,只有打勾或沒打勾,所以可以用 checked 來得知現在 true / false。

這次要做的是有好幾組 checkbox ,可以複選,把這幾組 checkbox 的值放到一個陣列裡,再顯示到 <p> 裡面:

template:

<div class="service-content">
    <label>service:</label>
    <input
        type="checkbox"
        value="good-service"
        id="good-service" />
    <label for="good-service">very good</label>
    <input
        type="checkbox"
        value="normal-service"
        id="normal-service"/>
    <label for="normal-service">normal</label>
    <input
        type="checkbox"
        value="bad-service"
        id="bad-service" />
    <label for="bad-service">bad</label>
</div>
<p></p>

javascript:

const serviceArray = [];

const good = document.querySelector('#good-service')
const normal = document.querySelector('#normal-service')
const bad = document.querySelector('#bad-service')
const serviceText = document.querySelector('p')

// 監聽每個的change事件
good.addEventListener('change', function() {	
	if(good.checked) {
	  serviceArray.push(good.value);		
	} else {
	  const index = serviceArray.indexOf('good-service');
	  serviceArray.splice(index, 1);
	}	
	  serviceText.textContent = serviceArray;		
})

normal.addEventListener('change', function() {	
	if(normal.checked) {
	  serviceArray.push(normal.value);	
	} else {
	  const index = serviceArray.indexOf('normal-service');
	  serviceArray.splice(index, 1);
	}
	  serviceText.textContent = serviceArray;		
})


bad.addEventListener('change', function() {	
	if(bad.checked) {
	  serviceArray.push(bad.value);	
	} else {
	  const index = serviceArray.indexOf('bad-service');
	  serviceArray.splice(index, 1);
	}	
	  serviceText.textContent = serviceArray;		
})

這樣寫落落長,超複雜的拉> <
要注意的是這裡都是用 input.value 來放進去 serviceArray。(在v-model裡面value是很重要的)

codepen: https://codepen.io/Jadddxx/pen/ExLOJXd?editors=0010

v-model

最前面有講到 v-model 是用綁定 value 跟監聽事件來完成的,所以有 value 的就要 綁同一個 v-model

javascript:
注意給的是一個陣列

const serviceArray = ref([]);

template:

<div class="service-content each-content">
    <label>service:</label>
    
    <input
    type="checkbox"
    value="good-service"
    id="good-service"
    v-model="serviceArray" />
    <label for="good-service">very good</label>
    
    <input
    type="checkbox"
    value="normal-service"
    id="normal-service"
    v-model="serviceArray" />
    <label for="normal-service">normal</label>
    
    <input
    type="checkbox"
    value="bad-service"
    id="bad-service"
    v-model="serviceArray" />
    <label for="bad-service">bad</label>
    
</div>
<p>{{ serviceArray }}</p>

而如果 serviceArray 給的是一個空字串的話,就等於全部的 value 都要共用一個 v-model ,所以會打勾一個變成全部都連動的,而這個 v-model 別無他法只能變成 true / false。

小結

  • checkbox 群組的話 v-model 要綁在每一個 input 身上,變數要用陣列才能夠複選。

一不小心 checkbox 程式碼爆表,分成兩天講,明天繼續 radio, select囉!


上一篇
Day26 前端蛇行撞牆記 - 在 Vue 3 偵測螢幕尺寸變化 / VueUse及原生JS
下一篇
Day28 前端蛇行撞牆記 - input 原生及 v-model 比較 / Vue 3 (下)
系列文
前端蛇行撞牆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言